// Rubik rotary entropy algorithm
// Rubik旋熵算法
/*
Copyright (C) 2025 LosefDevLab
RREA(2025) by LosefDevLab freedom-create in XFCSTD2.

RREA Random Algorithm Encapsulation
RREA的实现封装
*/

#ifndef RREA_HPP
#define RREA_HPP

#include <chrono>
#include <deque>
#include <iostream>
#include <random>
#include <vector>

using namespace std;

enum Color {
  RED = 'a',
  BLUE = 'b',
  YELLOW = 'c',
  WHITE = 'd',
  GREEN = 'e',
  ORANGE = 'f'
};
class RREA {
private:
  int size;                            // 魔方边长（Xa = Xb）
  vector<vector<vector<Color>>> cubeX; // 横圈三维数组
  vector<vector<vector<Color>>> cubeY; // 竖圈三维数组
  deque<int> lastGenerated;            // 防止低随机性
  mt19937 rng;

  void initializeCubes() {
    for (int i = 0; i < size; ++i) {
      for (int j = 0; j < size; ++j) {
        cubeX[0][i][j] = RED;
        cubeX[size - 1][i][j] = BLUE;
        cubeX[i][0][j] = GREEN;
        cubeX[i][size - 1][j] = YELLOW;
        cubeX[i][j][0] = WHITE;
        cubeX[i][j][size - 1] = ORANGE;
      }
    }

    cubeY = cubeX;
  }

public:
  RREA(int n)
      : size(n),
        rng(std::chrono::system_clock::now().time_since_epoch().count()) {
    cubeX.resize(size, vector<vector<Color>>(size, vector<Color>(size)));
    cubeY.resize(size, vector<vector<Color>>(size, vector<Color>(size)));
    initializeCubes();
  }

  // 旋转横圈（平行X轴，操作cubeX）
  void rotateXCircle(int layer, int steps) {
    steps %= 4;
    while (steps--) {
      Color temp = cubeX[layer][0][0];
      for (int i = 0; i < size - 1; ++i)
        cubeX[layer][0][i] = cubeX[layer][0][i + 1];
      for (int i = 0; i < size - 1; ++i)
        cubeX[layer][i][size - 1] = cubeX[layer][i + 1][size - 1];
      for (int i = size - 1; i > 0; --i)
        cubeX[layer][size - 1][i] = cubeX[layer][size - 1][i - 1];
      for (int i = size - 1; i > 1; --i)
        cubeX[layer][i][0] = cubeX[layer][i - 1][0];
      cubeX[layer][1][0] = temp;
    }
  }

  // 旋转竖圈（平行Y轴，操作cubeY）
  void rotateYCircle(int layer, int steps) {
    steps %= 4;
    while (steps--) {
      Color temp = cubeY[0][layer][0];
      for (int i = 0; i < size - 1; ++i)
        cubeY[i][layer][0] = cubeY[i + 1][layer][0];
      for (int i = 0; i < size - 1; ++i)
        cubeY[size - 1][layer][i] = cubeY[size - 1][layer][i + 1];
      for (int i = size - 1; i > 0; --i)
        cubeY[i][layer][size - 1] = cubeY[i - 1][layer][size - 1];
      for (int i = size - 1; i > 1; --i)
        cubeY[0][layer][i] = cubeY[0][layer][i - 1];
      cubeY[0][layer][1] = temp;
    }
  }

  int gen() {
    uniform_int_distribution<int> dist(1, size * 2);
    int attempt = 0;
    const int maxAttempts = 10; // 防止"防重复生成"导致的长时间循环
    int result;

    do {
      for (int i = 0; i < size; ++i) {
        rotateXCircle(i, dist(rng));
        rotateYCircle(i, dist(rng));
      }

      int sumX = 0, sumY = 0;
      for (int i = 0; i < size; ++i)
        for (int j = 0; j < size; ++j) {
          sumX += static_cast<int>(cubeX[0][i][j]);
          sumY += static_cast<int>(cubeY[0][i][j]);
        }

      result = (sumX + sumY) % 10;

      attempt++;
      if (attempt > maxAttempts)
        break;

    } while (containsLast(result));

    if (lastGenerated.size() >= 8)
      lastGenerated.pop_front();
    lastGenerated.push_back(result);

    return result;
  }

  // Debug Status
  void printCubes() {
    cout << "CubeX:\n";
    for (int k = 0; k < size; ++k) {
      cout << "Layer " << k << ":\n";
      for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j)
          cout << static_cast<char>(cubeX[k][i][j]) << " ";
        cout << "\n";
      }
      cout << "\n";
    }

    cout << "CubeY:\n";
    for (int k = 0; k < size; ++k) {
      cout << "Layer " << k << ":\n";
      for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j)
          cout << static_cast<char>(cubeY[k][i][j]) << " ";
        cout << "\n";
      }
      cout << "\n";
    }
  }
  bool containsLast(int value) const {
    for (int v : lastGenerated)
      if (v == value)
        return true;
    return false;
  }
};
#endif // RREA_HPP